import logging
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, NoSuchElementException

# 配置日志记录
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

class DoubanMovieCommentsScraper:
    def __init__(self, driver_path=None):
        options = webdriver.EdgeOptions()
        if driver_path:
            options.binary_location = driver_path
        self.driver = webdriver.Edge(options=options)

    def __del__(self):
        self.close_browser()

    def open_page(self, url):
        try:
            self.driver.get(url)
        except TimeoutException as e:
            logging.error(f"由于超时无法打开页面: {e}")
            return False
        except Exception as e:
            logging.error(f"无法打开页面: {e}")
            return False
        return True

    def wait_for_element(self, by, value, timeout=10):
        try:
            return WebDriverWait(self.driver, timeout).until(EC.presence_of_element_located((by, value)))
        except TimeoutException:
            logging.error(f"在 {timeout} 秒内未找到 {by}='{value}' 的元素")
            return None

    def wait_for_elements(self, by, value, timeout=10):
        try:
            return WebDriverWait(self.driver, timeout).until(EC.presence_of_all_elements_located((by, value)))
        except TimeoutException:
            logging.error(f"在 {timeout} 秒内未找到任何 {by}='{value}' 的元素")
            return []

    def get_element_text(self, element, css_selector, default='N/A'):
        try:
            return element.find_element(By.CSS_SELECTOR, css_selector).text
        except NoSuchElementException:
            return default

    def get_element_attribute(self, element, attribute, default='N/A'):
        try:
            return element.get_attribute(attribute)
        except NoSuchElementException:
            return default

    def extract_comment_details(self, comment):
        comment_id = self.get_element_attribute(comment, 'data-cid')

        user_info = comment.find_element(By.CSS_SELECTOR, 'div.avatar a')
        username = self.get_element_attribute(user_info, 'title')
        user_link = self.get_element_attribute(user_info, 'href')

        avatar = self.get_element_attribute(user_info.find_element(By.TAG_NAME, 'img'), 'src')

        # 确保有用人数存储在 span.votes.vote-count 中
        useful_count = self.get_element_text(comment, 'span.votes.vote-count', default='0')

        comment_text = self.get_element_text(comment, 'span.short')

        # 处理 span.rating 可能不出现的情况
        rating_element = comment.find_elements(By.CSS_SELECTOR, 'span.rating')
        rating = rating_element[0].get_attribute('title') if rating_element else 'N/A'

        comment_time = self.get_element_attribute(comment.find_element(By.CSS_SELECTOR, 'span.comment-time'), 'title')

        comment_location = self.get_element_text(comment, 'span.comment-location')

        return {
            "评论ID": comment_id,
            "用户名": username,
            "用户链接": user_link,
            "头像": avatar,
            "有用人数": useful_count,  # 添加有用人数到字典中
            "评论内容": comment_text,
            "评分": rating,
            "评论时间": comment_time,
            "评论地点": comment_location
        }

    def extract_comments(self):
        comments = self.wait_for_elements(By.CSS_SELECTOR, 'div.comment-item')
        for comment in comments:
            try:
                comment_details = self.extract_comment_details(comment)
                for key, value in comment_details.items():
                    print(f"{key}: {value}")
                print("-" * 50)
            except NoSuchElementException as e:
                logging.error(f"评论中未找到元素: {e}")

    def click_next_page(self):
        try:
            next_button = self.wait_for_element(By.CSS_SELECTOR, 'a.next')
            if next_button and 'disabled' not in next_button.get_attribute('class'):
                next_button.click()
                return True
            else:
                logging.info("没有更多页面可抓取。")
                return False
        except NoSuchElementException as e:
            logging.error(f"未找到下一页按钮: {e}")
            return False
        except Exception as e:
            logging.error(f"点击下一页失败: {e}")
            return False

    def scrape_all_pages(self, url):
        if not self.open_page(url):
            return
        while True:
            self.extract_comments()
            if not self.click_next_page():
                break
        self.close_browser()

    def close_browser(self):
        self.driver.quit()

if __name__ == "__main__":
    scraper = DoubanMovieCommentsScraper()
    scraper.scrape_all_pages("https://movie.douban.com/subject/21359690/comments?status=P")
